#ifndef _SSS_UTILS_H_
#define _SSS_UTILS_H_

#include "SSS_main.cuh"
#include <sys/time.h>
#include <cublas_v2.h>

#if defined (__cplusplus)
extern "C"
{
#endif    
double SSS_get_time(void);
void SSS_free(void *mem);


void SSS_mat_test_printf(SSS_MAT *A,int n);
void SSS_vec_test_printf(SSS_VEC *A,int n);

void SSS_mat_d2h(SSS_MAT *P);
void SSS_vec_d2h(SSS_VEC *A);


void SSS_device_array_zero(int n,double *d_val);


void SSS_device_matrix_zero(int n,int *d_val);

//计算向量b的L2范数
double SSS_blas_vec_norm2(const SSS_VEC *x);
double SSS_blas_vec_norm2_cuda(const SSS_VEC *x);

double SSS_blas_array_norm2(int n, const double *x);
double SSS_blas_array_norm2_cuda(int n, const double *x);

double SSS_blas_array_norminf(int n, const double *x);


//打印出迭代解算器的迭代信息
void SSS_print_itinfo(const int stop_type, const int iter, const double relres,
        const double absres, const double factor);

//Standard and aggressive coarsening schemes
void SSS_exit_on_errcode(const int status, const char *fctname);


//spmv
void SSS_blas_mv_mxy(const SSS_MAT *A, const SSS_VEC *x, SSS_VEC *y);
void spmv_cuda(int n,int *d_A_row_ptr,int *d_A_col_idx,double *d_A_val,double *d_x_val,double *d_y_val);

//alpha_spmv
void SSS_blas_mv_amxpy(double alpha, const SSS_MAT *A, const SSS_VEC *x, SSS_VEC *y);
void alpha_spmv_cuda(double alpha, int n,int *d_row_ptr,int * d_col_idx,double * d_A_val,double * d_x_val,double * d_y_val);

//dot
double SSS_blas_array_dot(int n, const double *x, const double *y);
double SSS_blas_array_dot_cuda(int n, const double *x, const double *y);
double SSS_blas_array_dot_cublas(cublasHandle_t handle , int n,  double *d_x, const double *d_y);

//axpy
void SSS_blas_array_axpy(int n, double a, const double *x, double *y);
void SSS_blas_array_axpy_cuda(int n, double a, const double *x, double *y);

//axpby
void SSS_blas_array_axpby(int n, double a, const double *x, double b, double *y);
void SSS_blas_array_axpby_cuda(int n, double a, const double *x, double b, double *y);

//ax
void SSS_blas_array_ax(int n, double a, double *x);
void SSS_blas_array_ax_cuda(int n, double a, double *x);

//Set initial value for an array to be x=Ax
void SSS_blas_array_set( int n, double *x, double Ax);

//spgemm cpu
SSS_MAT spgemm_hash( SSS_MAT *A, SSS_MAT *B,SSS_MAT *C);
SSS_MAT spgemm_spa( SSS_MAT *A, SSS_MAT *B,SSS_MAT *C);

//cusparse10.2_spgemm
SSS_MAT SSS_blas_spgemm_device( SSS_MAT *A,  SSS_MAT *B,SSS_MAT *C);

SSS_MAT SSS_blas_mat_rap_device(const SSS_MAT *R, const SSS_MAT *A, const SSS_MAT *P);

SSS_MAT SSS_RAP_device(const SSS_MAT *R, const SSS_MAT *A, const SSS_MAT *P);

#if defined (__cplusplus)
}
#endif
#endif